package com.weaver.dev.tools.openapi;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
import com.weaver.dev.tools.openapi.bean.MsgBean;
import com.weaver.dev.tools.openapi.config.WeaverOpenApiConfig;

import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class WeaverOpenApi {

    private String appKey;
    private String appSecret;
    private String corpid;

    private WeaverOpenApiConfig weaverOpenApiConfig;

    /**
     * 内部code token缓存
     */
    private Cache<String, String> cache = null;

    public WeaverOpenApi(String appKey, String appSecret, String corpid) {
        this(appKey, appSecret, corpid, new WeaverOpenApiConfig(), true);
    }

    public WeaverOpenApi(String appKey, String appSecret, String corpid, WeaverOpenApiConfig config) {
        this(appKey, appSecret, corpid, config, true);
    }

    public WeaverOpenApi(String appKey, String appSecret, String corpid, WeaverOpenApiConfig config, boolean isLazy) {
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.corpid = corpid;
        this.weaverOpenApiConfig = config;
        if (!isLazy) {
            // 获取一次token
            try {
                accessToken();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("token 加载异常: " + e.getMessage());
            }
        }
    }


    /**
     * 获取code信息
     */
    public String authorize() {
        Map<String, Object> params = Maps.newHashMap();
        params.put("corpid", corpid);
        params.put("response_type", "code");
        HttpRequest request = HttpUtil.createGet(this.weaverOpenApiConfig.getAuthorizeUrl());
        request.form(params);
        HttpResponse response = request.execute();
        if (response.isOk()) { // 请求成功
            String respStr = response.body();
            JSONObject jsonObj = JSONObject.parseObject(respStr);
            if (StrUtil.equals(jsonObj.getString("errcode"), "0")) {
                return jsonObj.getString("code");
            } else {
                throw new RuntimeException("请求失败：" + respStr);
            }
        } else {
            throw new RuntimeException("请求异常：" + response.body());
        }
    }

    public HttpResponse requestAccessToken() {
        Map<String, Object> params = Maps.newHashMap();
        params.put("app_key", appKey);
        params.put("app_secret", appSecret);
        params.put("grant_type", "authorization_code");
        params.put("code", authorize());
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getAccessTokenUrl());
        request.form(params);
        return request.execute();
    }

    private Map<String, Object> getTokenMap() {
        HttpResponse tokenRes = requestAccessToken();
        if (tokenRes.isOk()) {
            JSONObject res = JSON.parseObject(tokenRes.body());
            if (StrUtil.equals(res.getString("errcode"), "0")) {
                String token = res.getString("accessToken");
                long expiresTime = res.getLong("expires_in");
                Map<String, Object> resMap = Maps.newHashMap();
                resMap.put("token", token);
                resMap.put("time", expiresTime);
                return resMap;
            } else {
                throw new RuntimeException("获取token请求失败：" + res.getString("errmsg"));
            }
        } else {
            throw new RuntimeException("获取token请求异常: " + tokenRes.body());

        }
    }

    public String accessToken() throws ExecutionException {
        if (Objects.isNull(cache)) { // 如果是第一次，则构建缓存
            Map<String, Object> resMap = getTokenMap();
            this.cache = CacheBuilder.newBuilder()
                    .maximumSize(1)
                    .expireAfterWrite(Long.parseLong(Objects.requireNonNull(StrUtil.toString(resMap.get("time")))) - 300, TimeUnit.MINUTES)
                    .build();
            this.cache.put("token", Objects.requireNonNull(StrUtil.toString(resMap.get("token"))));
        }
        return cache.get("token", () -> StrUtil.toString(getTokenMap().get("token")));
    }

    public String etLoginToken(String account) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("app_key", appKey);
        params.put("app_security", appSecret);
        params.put("account", account);
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getLoginTokenUrl())
                .form(params );
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            if (StrUtil.equals(res.getString("errcode"), "0")) {
                return res.getString("etLoginToken");
            } else {
                throw new RuntimeException("获取token请求失败：" + res.getString("errmsg"));
            }
        } else {
            throw new RuntimeException("获取token请求异常: " + response.body());
        }

    }

    public OutputStream download(String fileId) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("app_key", appKey);
        params.put("app_security", appSecret);
        return null;
    }

    /**
     * 查询会议室使用情况
     * @param startDate 开始日期
     * @param endDate 结束日期
     */
    public JSONArray queryRoomEvents(String userid, Date startDate, Date endDate) throws ExecutionException {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userid", Long.parseLong(userid));
        params.put("access_token", accessToken());
        params.put("start", DateUtil.format(startDate, "yyyy-MM-dd HH:mm:ss"));
        params.put("end", DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss"));
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getQueryEventsUrl())
                .form(params);
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            if (StrUtil.equals(res.getJSONObject("message").getString("errcode"), "0") || StrUtil.equals(res.getJSONObject("message").getString("errcode"), "200")) {
                return res.getJSONArray("events");
            } else {
                throw new RuntimeException("请求失败：" + res.getJSONObject("message").getString("errmsg"));
            }
        } else {
            throw new RuntimeException("请求异常: " + response.body());
        }
    }

    /**
     * 获取人员日报数据
     * @param userids 用户ID集合
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return
     */
    public JSONArray queryBlog(List<String> userids, Date startDate, Date endDate) throws ExecutionException {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userIds", userids);
        params.put("access_token", accessToken());
        params.put("startDate", DateUtil.format(startDate, "yyyy-MM-dd"));
        params.put("endDate", DateUtil.format(endDate, "yyyy-MM-dd"));
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getQueryBlogUrl())
                .form(params);
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            if (StrUtil.equals(res.getJSONObject("message").getString("errcode"), "0") || StrUtil.equals(res.getJSONObject("message").getString("errcode"), "200")) {
                return res.getJSONArray("data");
            } else {
                throw new RuntimeException("请求失败：" + res.getJSONObject("message").getString("errmsg"));
            }
        } else {
            throw new RuntimeException("请求异常: " + response.body());
        }
    }

    /**
     * 创建流程审批
     * @return
     */
    public JSONObject workflowCreate(String userid, String workflowid, String flowname, Map<String, Object> datamap) throws ExecutionException {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userid", userid);
        params.put("access_token", accessToken());
        params.put("flowName", flowname);
        params.put("id", workflowid);
        // 处理datamap
        params.put("datamap", datamap);
        System.out.println(JSON.toJSONString(params));
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getWorkflowCreateUrl())
                .form(params);
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            return res;
        } else {
            throw new RuntimeException("请求异常: " + response.body());
        }
    }

    public JSONObject getFieldIdById(String userid, String formid) throws ExecutionException {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userid", userid);
        params.put("access_token", accessToken());
        params.put("id", formid);
        HttpRequest request = HttpUtil.createGet(this.weaverOpenApiConfig.getWorkflowFieldIdUrl())
                .form(params);
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            return res;
        } else {
            throw new RuntimeException("请求异常: " + response.body());
        }
    }

    public JSONObject sendMsg(MsgBean msgBean) throws ExecutionException {
        JSONObject params = JSONObject.parseObject(JSON.toJSONString(msgBean));
        params.put("access_token", accessToken());
        HttpRequest request = HttpUtil.createPost(this.weaverOpenApiConfig.getSendMsgUrl())
                .body(params.toJSONString());
        HttpResponse response = request.execute();
        if (response.isOk()) {
            JSONObject res = JSON.parseObject(response.body());
            return res;
        } else {
            throw new RuntimeException("请求异常: " + response.body());
        }
    }


    public static void main(String[] args) throws ExecutionException {
        String appKey = "8f986579e31a9456ff905da071707b86";
        String appSecret = "75cc7e693d178b4231d9b260573570b5";
        String hostUrl = "https://api.yunteams.cn";
        String corpid = "fba4c42719388ab433252691850c367e";
        WeaverOpenApi weaverOpenApi = new WeaverOpenApi(appKey, appSecret, corpid, new WeaverOpenApiConfig() {
            @Override
            public String getHostUrl() {
                return hostUrl;
            }
        });

//        System.out.println(weaverOpenApi.accessToken());
//
//        System.out.println(weaverOpenApi.etLoginToken("18757432199"));
//        weaverOpenApi.queryRoomEvents("8514074616793847943", DateUtil.parse("2022-07-02 01:00:00", "yyyy-MM-dd HH:mm:ss").toJdkDate(), DateUtil.parse("2022-07-02 23:00:00", "yyyy-MM-dd HH:mm:ss").toJdkDate());
//        // 下载文件
////        /api/file/v2/common/download/{fileId}
//        weaverOpenApi.queryBlog(Lists.newArrayList("8514074616793847943"), DateUtil.parse("2022-07-02", "yyyy-MM-dd").toJdkDate(), DateUtil.parse("2022-07-02", "yyyy-MM-dd").toJdkDate());
        Map<String, Object> datamap = Maps.newHashMap();
        datamap.put("7835657919042873041", "是");
        JSONObject res = weaverOpenApi.workflowCreate("8514074616793847943",
                "744691228381798401", "短信通知-openapi创建", datamap);
        System.out.println(res.toJSONString());

        JSONObject queryRes = weaverOpenApi.getFieldIdById("8514074616793847943", "5955657918675533330");
        System.out.println(queryRes.toJSONString());
    }

}
